package com.mlh.linkedlist;

import com.mlh.greed.柠檬水找零;

//给你一个长度为 n 的链表，每个节点包含一个额外增加的随机指针 random ，该指针可以指向链表中的任何节点或空节点。
// 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成，其中每个新节点的值都设为其对应的原节点的值。
// 新节点的 next 指针和 random 指针也都应指向复制链表中的新节点，并使原链表和复制链表中的这些指针能够表示相同的链表状态。
// 复制链表中的指针都不应指向原链表中的节点 。
// 返回复制链表的头节点。
public class 随机链表的复制 {
    //    这道题的难点在于怎么复制随机指针
    //     解题的关键在于怎么怎么存储新节点
    //     第一种解法：就是将构造一个Map<node,newNode>  这个数据结构出来后就很好解题
    //     第二种解法：根据遍历到的原节点创建对应的新节点，每个新创建的节点接到原节点的后面
    //     形成新-旧-新-旧-新-旧这样的结构 也很好解题
    public Node method1(Node head) {
        if(head==null){
            return null;
        }
        Node temp=head;
        //完成除随机指针的复制
        while (temp!=null){
            Node help=new Node(temp.val);
            help.next=temp.next;
            temp.next=help;
            temp=temp.next.next;
        }
        //接下来完成对随机指针的复制
        temp=head;
        while (temp!=null){
            if(temp.random==null){
               temp.next.random=null;
            }else {
                temp.next.random=temp.random.next;
            }
            temp=temp.next.next;
        }
        //把新链表从旧链表中分离出来
        temp=head;
        //新链表的头节点
        Node headNew=head.next;
        Node temp2=headNew;
        while(temp!=null){
            temp.next=temp.next.next;
            if(temp2.next!=null){
                temp2.next=temp2.next.next;
            }
            temp=temp.next;
            temp2=temp2.next;
        }
        return headNew;
    }

    //带随机指针的节点
    class Node {
        int val;
        Node next;
        Node random;

        public Node(int val) {
            this.val = val;
            this.next = null;
            this.random = null;
        }
    }
    public Node practice(Node head) {
        if(head==null){
            return null;
        }
        Node cur=head;
        //构建新旧节点链表
        while(cur!=null){
            Node copy=new Node(cur.val);
            Node curNext=cur.next;
            cur.next=copy;
            cur=curNext;
            copy.next=curNext;
        }
        cur=head;
        //补充新节点的随机节点
        while (cur!=null){
            if(cur.random==null){
                cur.next.random=null;
            }else{
                cur.next.random=cur.random.next;
            }
            cur=cur.next.next;
        }
        //将新节点摘出来，生成新链表
        cur=head;
        Node sentry=new Node(-1),newHead=sentry;
        while (cur!=null){
            sentry.next=cur.next;
            cur.next=cur.next.next;
            sentry=sentry.next;
            sentry.next=null;
            cur=cur.next;
        }
        return newHead.next;
    }

    public Node practice2(Node head) {
        if(head==null){
            return null;
        }
        Node sentry=head;
        while (head!=null){
            Node copy=new Node(head.val);
            Node temp=head.next;
            head.next=copy;
            copy.next=temp;
            head=head.next.next;
        }
        head=sentry;
        while(head!=null){
            if(head.random!=null){
                head.next.random=head.random.next;
            }
            head=head.next.next;
        }
        head=sentry;
        sentry=sentry.next;
        Node pre=new Node(0);
        while(head!=null){
            pre.next=head.next;
            head.next=head.next.next;
            head=head.next;
            pre=pre.next;
        }
        return sentry;
    }
}
